package com.ddfeiyu;


import com.ddfeiyu.redis.properties.RedisProperties;
import com.ddfeiyu.redis.util.RedisQueueUtil;
import com.ddfeiyu.server.NettyServer;
import com.ddfeiyu.server.properties.ServerProperties;
import com.ddfeiyu.util.NetUtils;
import io.netty.channel.Channel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.*;

//自动加载配置信息
@Configuration
@EnableAutoConfiguration
@EnableConfigurationProperties({ServerProperties.class, RedisProperties.class})
//使包路径下带有@Value的注解自动注入
// 使包路径下带有@Autowired的类可以自动注入
@ComponentScan("com.ddfeiyu")
@SpringBootApplication
public class NettyServerApplication implements CommandLineRunner {

	private static Logger logger = LoggerFactory.getLogger(NettyServerApplication.class);

	//默认线程池
	private static ExecutorService executorService = Executors.newFixedThreadPool(2);

	private static ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);

	@Autowired
	private NettyServer nettyServer;
	@Autowired
	private RedisQueueUtil redisQueueUtil;
	@Autowired
	private ServerProperties serverProperties;


	public static void main(String[] args) throws Exception {
		SpringApplication.run(NettyServerApplication.class);
	}

	@Override
	public void run(String... args) throws Exception {
		// 定时注册ip端口；3秒后每5秒执行一次
		registerServerMeta();

		logger.info("NettyServer启动服务CommandLineRunner ");
		Future<Channel> future = executorService.submit(nettyServer);
		Channel channel = future.get();
		if (null == channel) {
			throw new RuntimeException("NettyServer启动服务CommandLineRunner start error channel is null");
		}

		// Channel状态定时巡检；3秒后每5秒执行一次
		reStartServer();
		logger.info("NettyServer启动服务CommandLineRunner完成 {}", channel.localAddress());
	}

	private void registerServerMeta(){
		scheduledExecutorService.scheduleAtFixedRate(()->{
			doRegisterServerMeta();
		}, 3, 5, TimeUnit.SECONDS);
	}

	private void doRegisterServerMeta(){
		if (nettyServer.isActive()){
			String localHost = NetUtils.getLocalHost();
			int port = serverProperties.getPort();
			redisQueueUtil.add2Set(RedisQueueUtil.DDFEIYU_SERVER_QUEUE, localHost + ":" + port);
			logger.info("---registerServerMeta,localHost:[ {} ], port:[ {} ]", localHost, port);
		}
	}

	private void reStartServer(){
		scheduledExecutorService.scheduleAtFixedRate(()->{
			doReStartServer();
			doRegisterServerMeta();
		}, 3, 5, TimeUnit.SECONDS);
	}

	private void doReStartServer(){
		while (!nettyServer.isActive()) {
			System.out.println("NettyServer启动服务CommandLineRunner ：通信管道巡检：通信管道状态 " + nettyServer.isActive());
			try {
				System.out.println("NettyServer启动服务CommandLineRunner：通信管道巡检：断线重连[Begin]");
				Channel freshChannel = executorService.submit(nettyServer).get();
				System.out.println("NettyServer启动服务CommandLineRunner：通信管道巡检：断线重连[End]");
			} catch (InterruptedException | ExecutionException e) {
				System.out.println("NettyServer启动服务CommandLineRunner：通信管道巡检：断线重连[Error]");
			}
		}
	}

}